import CryptoJS from 'crypto-js';
import { isNull } from 'lodash';
import uploadConfig from '@cwd/config/upload'
import { ElMessage } from 'element-plus'


const tool = {}

/**
 * LocalStorage
 */
tool.local = {
    set(table, settings) {
        let _set = JSON.stringify(settings)
        return localStorage.setItem(table, _set);
    },
    get(table) {
        let data = localStorage.getItem(table);
        try {
            data = JSON.parse(data)
        } catch (err) {
            return null
        }
        return data;
    },
    remove(table) {
        return localStorage.removeItem(table);
    },
    clear() {
        return localStorage.clear();
    }
}

/**
 * SessionStorage
 */
tool.session = {
    set(table, settings) {
        let _set = JSON.stringify(settings)
        return sessionStorage.setItem(table, _set);
    },
    get(table) {
        let data = sessionStorage.getItem(table);
        try {
            data = JSON.parse(data)
        } catch (err) {
            return null
        }
        return data;
    },
    remove(table) {
        return sessionStorage.removeItem(table);
    },
    clear() {
        return sessionStorage.clear();
    }
}

/**
 * CookieStorage
 */
tool.cookie = {
    set(name, value, config = {}) {
        const defaultConfig = {
            expires: null,
            path: null,
            domain: null,
            secure: false,
            httpOnly: false
        };
        const cfg = { ...defaultConfig, ...config };
        let cookieStr = `${name}=${encodeURIComponent(value)}`;

        if (cfg.expires) {
            const exp = new Date();
            exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000);
            cookieStr += `;expires=${exp.toGMTString()}`;
        }
        if (cfg.path) {
            cookieStr += `;path=${cfg.path}`;
        }
        if (cfg.domain) {
            cookieStr += `;domain=${cfg.domain}`;
        }
        if (cfg.secure) {
            cookieStr += `;secure`;
        }
        if (cfg.httpOnly) {
            // Note: HttpOnly cookies cannot be set via JavaScript. They must be set on the server.
            console.warn('HttpOnly cookies cannot be set via JavaScript');
        }
        document.cookie = cookieStr;
    },
    get(name) {
        const regex = new RegExp(`(^| )${name}=([^;]*)(;|$)`);
        const arr = document.cookie.match(regex);
        return arr ? decodeURIComponent(arr[2]) : null;
    },
    remove(name, path = '/') {
        const exp = new Date();
        exp.setTime(exp.getTime() - 1);
        let cookieStr = `${name}=;expires=${exp.toGMTString()};path=${path}`;
        document.cookie = cookieStr;
    }
}

/* 复制对象 */
tool.objCopy = (obj) => {
    if (obj === undefined) {
        return undefined
    }
    return JSON.parse(JSON.stringify(obj));
}
/**
 * 生成随机字符串
 * @returns string
 */
tool.generateId = () => {
    return Math.floor(Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000)
}

/**
 * 日期格式化
 * @param {Date|number|string} date - 日期对象或时间戳
 * @param {string} [fmt='yyyy-MM-dd hh:mm:ss'] - 格式化字符串
 * @param {string} [isDefault='-'] - 默认返回值
 * @returns {string} - 格式化后的日期字符串
 */
tool.dateFormat = (date, fmt = 'yyyy-MM-dd hh:mm:ss', isDefault = '-') => {
    // 处理 Unix 时间戳（秒）
    if (typeof date === 'string' || typeof date === 'number') {
        date = parseInt(date, 10);
        if (date.toString().length === 10) {
            date *= 1000;
        }
    }
    date = new Date(date);

    // 如果日期无效，返回默认值
    if (isNaN(date.valueOf())) {
        return isDefault;
    }
    const o = {
        "M+": date.getMonth() + 1,                 // 月份
        "d+": date.getDate(),                      // 日
        "h+": date.getHours(),                     // 小时
        "m+": date.getMinutes(),                   // 分
        "s+": date.getSeconds(),                   // 秒
        "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
        "S": date.getMilliseconds()               // 毫秒
    };
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    }
    for (let k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
            fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
        }
    }
    return fmt;
}

/**
 * 千分符分隔
 * @param {number|string} num
 * @returns {string}
 */
tool.groupSeparator = (num) => {
    // 将输入转换为字符串
    num = num.toString();
    // 确保字符串包含小数点
    if (!num.includes('.')) {
        num += '.';
    }
    // 添加千分符
    const formattedNum = num.replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
        return $1 + ',';
    });
    // 去掉最后可能添加的多余小数点
    return formattedNum.replace(/\.$/, '');
}

/**
 * md5 加密
 * @param {string}
 */
tool.md5 = (str) => {
    return CryptoJS.MD5(str).toString()
}

/**
 * base64 加密 解密
 * @param {string}
 */
tool.base64 = {
    encode(data) {
        return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
    },
    decode(cipher) {
        return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
    }
}

/**
 *  aes 加密
 */
tool.aes = {
    encode(data, secretKey) {
        const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return result.toString();
    },
    decode(cipher, secretKey) {
        const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        });
        return CryptoJS.enc.Utf8.stringify(result);
    }
}

/**
 * 格式化字符大小
 * @param {*} size 
 * @returns 
 */
tool.formatSize = (size) => {
    if (typeof size === 'undefined') {
        return '0';
    }
    const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
    let index = 0;
    while (size >= 1024 && index < units.length - 1) {
        size /= 1024;
        index++;
    }
    return size.toFixed(2) + ' ' + units[index];
}


/**
 * 对象转url参数
 * @param {*} data
 * @param {*} isPrefix
 */
tool.httpBuild = (data, isPrefix = false) => {
    const prefix = isPrefix ? '?' : '';
    const _result = [];
    for (const key in data) {
        if (Object.prototype.hasOwnProperty.call(data, key)) {
            const value = data[key];
            // 去掉为空的参数
            if (['', undefined, null].includes(value)) {
                continue;
            }
            if (Array.isArray(value)) {
                value.forEach(_value => {
                    _result.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(_value)}`);
                });
            } else {
                _result.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
            }
        }
    }
    return _result.length ? prefix + _result.join('&') : '';
}
/**
 * 获取url 地址参数
 * @param {*} url 
 * @returns 
 */
tool.getRequestParams = (url) => {
    const theRequest = {};
    if (url.indexOf('?') !== -1) {
        const params = url.split('?')[1].split('&');

        params.forEach(param => {
            const [key, value] = param.split('=');
            if (key) {
                try {
                    theRequest[key] = value ? decodeURIComponent(value) : '';
                } catch (e) {
                    console.error('Error decoding parameter:', key, value);
                }
            }
        });
    }
    return theRequest;
}
/**
 * 获取图片
 * @param {*} path 
 * @param {*} defaultStorage 
 * @returns 
 */
tool.attachUrl = (path, defaultStorage = 'LOCAL') => {
    const isNetworkLink = /^https?:\/\//i.test(path);
  
    if (isNetworkLink) {
      return path;
    }
	return uploadConfig.storage[defaultStorage] + path
}

/**
 * 获取token
 */
tool.getToken = () => {
    return tool.local.get(import.meta.env.VITE_APP_TOKEN_PREFIX)
}

/**
* 转Unix时间戳
*/
tool.toUnixTime = (date) => {
    return Math.floor((new Date(date)).getTime() / 1000)
}

/**
 * 密码强度验证
 * @param {*} str 
 */
tool.pwdStrength = (password, strength = 3) => {
    const errors = [];

    // 检查密码长度
    if (password.length < 6) {
        errors.push('密码长度必须至少为 8 个字符');
    }

    // 检查是否包含字母
    if (!/[A-Za-z]/.test(password)) {
        errors.push('密码必须包含至少一个字母');
    }

    // 检查是否包含数字
    if (!/[0-9]/.test(password)) {
        errors.push('密码必须包含至少一个数字');
    }

    return {
        isValid: errors.length === 0,
        errors: errors
    };
}
/**
 * 
 */
tool.arrSum = (arr) => {
    let sum = 0;
    arr.forEach(item => sum += item);
    return sum;
};


/**
 * @param {*} fn 要执行的函数
 * @param {*} delay 延迟时间
 * @returns 
 */
tool.debounce = (fn, delay) => {
    let timeout = null;
    return function () {
        let context = this;
        let args = arguments;
        if (timeout) clearTimeout(timeout);
        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, delay);
        if (callNow) fn.apply(context, args);
    };
}
/**
 * 颜色转换为 rgba
 * @param {*} hexColor 
 * @param {*} alpha 
 * @returns 
 */
tool.generateRgba = (hexColor, alpha) => {
    let r = parseInt(hexColor.slice(1, 3), 16),
        g = parseInt(hexColor.slice(3, 5), 16),
        b = parseInt(hexColor.slice(5, 7), 16);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}


/* Fullscreen */
tool.screen = (element) => {
    let isFull = !!(document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement);
    if (isFull) {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
    } else {
        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        }
    }
}
/** 通过指定 `key` 获取父级路径集合，默认 `key` 为 `path` */
tool.getParentPaths = (value, routes, key = "path") => {
    // 深度遍历查找
    function dfs(routes, value, parents) {
        for (let i = 0; i < routes.length; i++) {
            const item = routes[i];
            // 返回父级path
            if (item[key] === value) return parents;
            // children不存在或为空则不递归
            if (!item.children || !item.children.length) continue;
            // 往下查找时将当前path入栈
            parents.push(item.path);

            if (dfs(item.children, value, parents).length) return parents;
            // 深度遍历查找未找到时当前path 出栈
            parents.pop();
        }
        // 未找到时返回空数组
        return [];
    }

    return dfs(routes, value, []);
}
/** 查找对应 `path` 的路由信息 */
tool.findRouteByPath = (path, routes) => {
    let res = routes.find((item) => item.path == path);
    if (res) {
        return isProxy(res) ? toRaw(res) : res;
    } else {
        for (let i = 0; i < routes.length; i++) {
            if (
                routes[i].children &&
                routes[i].children.length > 0
            ) {
                res = findRouteByPath(path, routes[i].children);
                if (res) {
                    return isProxy(res) ? toRaw(res) : res;
                }
            }
        }
        return null;
    }
}
/**
 * 是否图片上传
 * @param {*} file 
 * @returns 
 */
tool.isPicUpload = (file) => {
    const typeArry = ['.jpg', '.png', 'jpeg', '.JPG', '.PNG', '.JPEG', '.gif', '.GIF'];
    const type = file.name.substring(file.name.lastIndexOf('.'));
    const isImage = typeArry.indexOf(type) > -1;
    if (!isImage) {
        ElMessage.error('上传图片格式不对');
    }
    return isImage;
}


tool.download = (res, downName = '') => {
    const aLink = document.createElement('a');
    let fileName = downName
    let blob = res //第三方请求返回blob对象
  
    //通过后端接口返回
    if (res.headers && res.data) {
        blob = new Blob([res.data], {
          type: res.headers['content-type']?.replace(';charset=utf8', '') || 'application/octet-stream'
        });
      
        // 提取文件名
        if (!downName) {
          const disposition = decodeURIComponent(res.headers['content-disposition'] || '');
          let fileName = 'download.xlsx'; // 默认名
      
          const matches = disposition.match(/filename\*=UTF-8''(.+)/i);
          if (matches && matches[1]) {
            fileName = decodeURIComponent(matches[1]);
          } else {
            const fallback = disposition.match(/filename="?([^"]+)"?/i);
            if (fallback && fallback[1]) {
              fileName = fallback[1];
            }
          }
      
          downName = fileName;
        }
      }
      
    
    aLink.href = URL.createObjectURL(blob)
    // 设置下载文件名称
    aLink.setAttribute('download', fileName)
    document.body.appendChild(aLink)
    aLink.click()
    document.body.removeChild(aLink)
    URL.revokeObjectURL(aLink.href)
  }
  

export default tool
